﻿using System;
using System.IO;
using System.Collections.Generic;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;

namespace TheClerk.Forms.Templates.raw.Envelope
{
    #region internal Proofs
    /// <summary>
    /// List of Proof
    /// </summary>
    /// <remarks>-- Signatures by all of the end-entity keys asserted
    /// Proofs ::= SEQUENCE(1..MAX) OF Proof
    /// </remarks>
    internal class Proofs
    {
        internal List<Proof> data = new List<Proof>();
        internal List<Chop> chops = new List<Chop>();

        private byte[] AssertionCommitmentDER;

        private readonly string[] digestAlgorithms = { "SHA1", "SHA384", "RIPEMD160", "GOST3411" };



        public Proofs()
        {
            // TODO: Complete member initialization
            // cannot rely on having ACder when this object is constructed,
            // Payload.AddChop calls EnvelopeContent.AddChop calls
            // Proofs.AddChop.
        }

        public void AddChop(Chop input)
        {
            chops.Add(input);
            foreach (var i in data)
            {
                if (i != null)
                    i.EquipChop(input);
            }
        }


        /*
            // FIXME this code needs to be in Proofs, not EnvelopeContent
            foreach (Chop i in chops)
            {
                var ecdsaSigner = new Org.BouncyCastle.Crypto.Signers.ECDsaSigner();
                ecdsaSigner.Init(true, i.PrivateKey);
                var sha1Digest = new Org.BouncyCastle.Crypto.Digests.Sha1Digest();
                sha1Digest.Reset();
                var dsaDigestSigner = new Org.BouncyCastle.Crypto.Signers.DsaDigestSigner(ecdsaSigner, sha1Digest);
                dsaDigestSigner.Init(true, i.PrivateKey);
                dsaDigestSigner.BlockUpdate(ACder, 0, ACder.Length);
                var generatedSignature = dsaDigestSigner.GenerateSignature();

                var s = new System.IO.MemoryStream();
                var b = new Org.BouncyCastle.Asn1.DerSequenceGenerator(s);
                b.AddObject(Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.ECDsaWithSha1);
                b.AddObject(new Org.BouncyCastle.Asn1.DerOctetString(generatedSignature));
                b.Close();
                s.Seek(0, SeekOrigin.Begin);
                dsg.AddObject(Org.BouncyCastle.Asn1.Asn1Object.FromStream(s));
            }
        */

        internal Stream Serialize()
        {
            System.Diagnostics.Debug.Assert(chops.Count > 0);
            foreach (var c in chops)
            {
                foreach (var i in digestAlgorithms)
                {
                    data.Add(new Proof(Org.BouncyCastle.Security.DigestUtilities.GetDigest(i),
                        new MemoryStream(AssertionCommitmentDER),
                        c));
                }
            }
            MemoryStream s = new MemoryStream();
            var dsg = new DerSequenceGenerator(s);
            foreach (var i in data)
                dsg.AddObject(i.ToAsn1Encodable());
            dsg.Close();
            s.Position = 0;
            return s;
        }

        internal Asn1Encodable ToAsn1Encodable()
        {
            return Asn1Object.FromStream(Serialize());
        }


        internal byte[] ToByteArray()
        {
            var s = Serialize();
            var b = new byte[s.Length];
            s.Read(b, 0, b.Length);
            return b;
        }

        internal void SetACContent(byte[] ACder)
        {
            this.AssertionCommitmentDER = ACder;
        }
    }
    #endregion
}